打包项目:Rollup + SWC 打包
上一节我们使用 webpack + swc-loader 进行打包,构建时间约 3 秒。本节使用 Rollup 配合 SWC 进行打包对比,评估两者的构建效率和适用性。Rollup 以其高效的 Tree-shaking 和更小的输出体积而著称。
构建效率对比基准
| 方案 | 构建时间 | 输出 |
|---|---|---|
| SWC 编译(仅语法转换) | ~160ms | 保持源码目录结构 |
| webpack + swc-loader | ~3.0-3.4s | 单文件 bundle.js |
| Rollup + SWC | ~2.4-2.9s | 单文件 main.js |
安装 Rollup 依赖
pnpm add -D rollup @rollup/plugin-terser @rollup/plugin-commonjs @rollup/plugin-json @rollup/plugin-node-resolve @rollup/plugin-alias rollup-plugin-swc
bash
| 包名 | 用途 |
|---|---|
rollup | Rollup 核心 |
@rollup/plugin-node-resolve | 解析 node_modules 中的模块 |
@rollup/plugin-commonjs | 将 CommonJS 模块转换为 ES Module |
@rollup/plugin-json | 导入 JSON 文件 |
@rollup/plugin-terser | 代码压缩 |
@rollup/plugin-alias | 路径别名解析 |
rollup-plugin-swc | SWC 编译插件 |
方案一:对 dist 目录打包
SWC 先将 TS 编译为 JS(保持目录结构),然后 Rollup 对编译后的 dist 目录进行打包:
// rollup.config.js
import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import json from '@rollup/plugin-json'
import terser from '@rollup/plugin-terser'
export default {
input: 'dist/main.js', // SWC 编译后的入口文件
output: {
file: 'bundle/main.cjs',
format: 'cjs',
},
plugins: [
resolve({
extensions: ['.ts', '.js'],
preferBuiltins: true,
}),
commonjs(),
json(),
terser(),
],
external: (id) => /node_modules/.test(id), // 排除 node_modules
}
javascript
执行流程:
# Step 1: SWC 编译(~160ms)
nest build
# Step 2: Rollup 打包(~2.7s)
npx rollup -c
bash
方案二:直接从 TS 源码打包(推荐)
使用 rollup-plugin-swc 直接从 TypeScript 源码编译打包,跳过 nest build 步骤:
// rollup.config.js
import { fileURLToPath } from 'url'
import path from 'path'
import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import json from '@rollup/plugin-json'
import alias from '@rollup/plugin-alias'
import swc from 'rollup-plugin-swc'
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
// 屏蔽不需要的 warnings
const ignoreWarnings = ['UNRESOLVED_IMPORT', 'EVAL']
const ignoreModules = ['prisma-client']
export default {
input: 'src/main.ts',
output: {
file: 'dist/main.js',
format: 'cjs',
},
plugins: [
resolve({
extensions: ['.ts', '.js'],
preferBuiltins: true,
}),
commonjs(),
json(),
alias({
entries: [
{
find: '@',
replacement: path.resolve(__dirname, 'src'),
},
{
find: 'prisma-client',
replacement: path.resolve(__dirname, 'prisma/client'),
},
],
}),
swc(), // 默认读取 .swcrc 配置
],
external: (id) => /node_modules/.test(id),
onwarn(warning, warn) {
// 屏蔽 Prisma 等模块的 warning
if (ignoreWarnings.includes(warning.code)) return
if (warning.code === 'EVAL' && ignoreModules.some((m) => warning.id?.includes(m))) return
warn(warning)
},
}
javascript
关于 ESM 配置
由于 rollup.config.js 使用 ESM 语法,需要确保 package.json 中支持 ESM 或在命令中指定:
# 方式一:在 rollup.config.js 文件名后加 .cjs 后缀使用 CommonJS
# 方式二:命令行指定格式
npx rollup -c rollup.config.js --format cjs
# 方式三:在 package.json 中添加 "type": "module"
bash
由于我们的 NestJS 项目不是纯 ESM 项目,推荐使用方式二的命令行参数。
alias 配置说明
NestJS 项目中通常使用路径别名(如 @/ 映射到 src/),需要在 Rollup 中配置对应的 alias 插件:
| 别名 | 映射路径 | 说明 |
|---|---|---|
@ | src/ | 项目源码根目录 |
prisma-client | prisma/client/ | Prisma 生成的客户端文件 |
onwarn 配置
Prisma 生成的 Client 代码中会使用 eval,Rollup 会对此发出警告。通过 onwarn 回调屏蔽这些不影响功能的警告:
onwarn(warning, warn) {
const suppressCodes = ['UNRESOLVED_IMPORT', 'THIS_IS_UNDEFINED']
if (suppressCodes.includes(warning.code)) return
// 屏蔽 Prisma Client 的 eval 警告
if (warning.code === 'EVAL' && warning.id?.includes('prisma')) return
warn(warning)
}
javascript
构建与验证
# 执行打包
npx rollup -c rollup.config.js
# 验证输出
ls dist/
# main.js
# 运行
node dist/main.js
bash
验证步骤:
- 服务是否正常启动
- 接口是否正常响应(如登录接口测试)
- 无报错信息
package.json 脚本配置
将 Rollup 打包集成到构建流程中:
{
"scripts": {
"build": "nest build",
"build:prod": "node scripts/build.mjs",
"pack": "rollup -c rollup.config.js",
"build:all": "pnpm build:prod && pnpm pack"
}
}
json
Rollup vs webpack 最终对比
| 维度 | webpack + swc-loader | Rollup + SWC |
|---|---|---|
| 构建时间 | ~3.0-3.4s | ~2.4-2.9s |
| 配置复杂度 | 中等 | 中等 |
| Tree-shaking | 支持(需配置) | 原生支持 |
| 输出格式 | 丰富(CJS/ESM/IIFE/UMD) | 丰富(CJS/ESM/IIFE/UMD) |
| 插件生态 | 最大 | 丰富 |
| 适合场景 | 复杂前端应用 | 库打包、Node.js 服务打包 |
| 与 SWC 集成 | swc-loader | rollup-plugin-swc |
清理 webpack 依赖
如果决定使用 Rollup,可以移除 webpack 相关依赖:
# 移除 webpack 相关
pnpm remove webpack webpack-cli swc-loader
# 确保 nest-cli.json 中 webpack 为 false
# { "compiler": { "webpack": false } }
bash
小结
本节完成了 Rollup + SWC 打包方案的配置和验证:
- Rollup 构建速度比 webpack 快约 0.6-0.8 秒,整体效率更高
- 两种打包方案:先 SWC 编译再 Rollup 打包,或直接使用 rollup-plugin-swc
@rollup/plugin-alias处理路径别名,onwarn屏蔽 Prisma 的 eval 警告external排除node_modules,避免将依赖打包进输出文件- 推荐在生产环境中使用 Rollup + SWC 方案,保留
rollup.config.js配置
↑